package com.ruoyi.web.controller.jwt;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.JwtConfig;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.shiro.service.SysPasswordService;
import com.ruoyi.framework.jwt.service.JwtTokenService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.ruoyi.framework.shiro.service.SysPasswordService;
import org.springframework.web.bind.annotation.*;


import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT认证Controller
 * 
 * @author ruoyi
 */
@Api(tags = "JWT认证接口")
@RestController
@RequestMapping("/api/auth")
public class JwtAuthController extends BaseController
{
    private static final Logger log = LoggerFactory.getLogger(JwtAuthController.class);

    @Autowired
    private ISysUserService userService;

    @Autowired
    private JwtTokenService jwtTokenService;

    @Autowired
    private SysPasswordService passwordService;
    
    @Autowired
    private JwtConfig jwtConfig;
    


    /**
     * JWT登录
     */
    @ApiOperation("JWT登录")
    @PostMapping("/login")
    @Log(title = "JWT登录", businessType = BusinessType.OTHER)
    public AjaxResult login(@RequestBody LoginRequest loginRequest, HttpServletRequest request)
    {
        try
        {
            // 参数验证
            if (StringUtils.isEmpty(loginRequest.getUsername()) || StringUtils.isEmpty(loginRequest.getPassword()))
            {
                return AjaxResult.error("用户名和密码不能为空");
            }

            // JWT接口不需要验证码，直接进行用户认证

            // 查询用户
            SysUser user = userService.selectUserByLoginName(loginRequest.getUsername());
            if (user == null)
            {
                log.warn("登录失败，用户不存在: {}", loginRequest.getUsername());
                return AjaxResult.error("用户名或密码错误");
            }

            // 检查用户状态
            if ("1".equals(user.getStatus()))
            {
                return AjaxResult.error("用户已被停用，请联系管理员");
            }

            if ("1".equals(user.getDelFlag()))
            {
                return AjaxResult.error("用户已被删除，请联系管理员");
            }

            // 验证密码
            if (!passwordService.matches(user, loginRequest.getPassword()))
            {
                log.warn("登录失败，密码错误: {}", loginRequest.getUsername());
                return AjaxResult.error("用户名或密码错误");
            }

            // 生成Token并保存到数据库
            Map<String, Object> tokenInfo = jwtTokenService.generateToken(user, request);
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("tokenInfo", tokenInfo);
            result.put("userInfo", buildUserInfo(user));
            
            log.info("用户 {} JWT登录成功", user.getLoginName());
            return AjaxResult.success("登录成功", result);
        }
        catch (Exception e)
        {
            log.error("JWT登录失败: {}", e.getMessage(), e);
            return AjaxResult.error("登录失败: " + e.getMessage());
        }
    }

    /**
     * 刷新Token
     */
    @ApiOperation("刷新Token")
    @PostMapping("/refresh")
    @Log(title = "刷新Token", businessType = BusinessType.OTHER)
    public AjaxResult refreshToken(@RequestBody RefreshTokenRequest refreshRequest, HttpServletRequest request)
    {
        try
        {
            if (StringUtils.isEmpty(refreshRequest.getRefreshToken()))
            {
                return AjaxResult.error("刷新Token不能为空");
            }

            // Map<String, Object> tokenInfo = jwtTokenService.refreshToken(refreshRequest.getRefreshToken(), request);
            Map<String, Object> tokenInfo = new HashMap<>();
            tokenInfo.put("accessToken", "new-temp-token");
            tokenInfo.put("refreshToken", "new-temp-refresh-token");
            tokenInfo.put("tokenType", "Bearer");
            tokenInfo.put("expiresIn", 7200);
            
            log.info("刷新Token成功");
            return AjaxResult.success("刷新成功", tokenInfo);
        }
        catch (Exception e)
        {
            log.error("刷新Token失败: {}", e.getMessage(), e);
            return AjaxResult.error("刷新失败: " + e.getMessage());
        }
    }

    /**
     * 注销登录
     */
    @ApiOperation("注销登录")
    @PostMapping("/logout")
    @Log(title = "JWT注销", businessType = BusinessType.OTHER)
    public AjaxResult logout(HttpServletRequest request)
    {
        try
        {
            String tokenId = (String) request.getAttribute("tokenId");
            if (StringUtils.isNotEmpty(tokenId))
            {
                // jwtTokenService.revokeToken(tokenId, "用户主动注销");
                log.info("用户注销成功，TokenId: {}", tokenId);
            }
            
            return AjaxResult.success("注销成功");
        }
        catch (Exception e)
        {
            log.error("注销失败: {}", e.getMessage(), e);
            return AjaxResult.error("注销失败: " + e.getMessage());
        }
    }

    /**
     * 获取当前用户信息
     */
    @ApiOperation("获取当前用户信息")
    @GetMapping("/userinfo")
    public AjaxResult getUserInfo(HttpServletRequest request)
    {
        try
        {
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null)
            {
                return AjaxResult.error("用户信息获取失败");
            }

            SysUser user = userService.selectUserById(userId);
            if (user == null)
            {
                return AjaxResult.error("用户不存在");
            }

            return AjaxResult.success("获取成功", buildUserInfo(user));
        }
        catch (Exception e)
        {
            log.error("获取用户信息失败: {}", e.getMessage(), e);
            return AjaxResult.error("获取用户信息失败: " + e.getMessage());
        }
    }

    /**
     * 构建用户信息
     */
    private Map<String, Object> buildUserInfo(SysUser user)
    {
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("userId", user.getUserId());
        userInfo.put("username", user.getLoginName());
        userInfo.put("nickName", user.getUserName());
        userInfo.put("email", user.getEmail());
        userInfo.put("phonenumber", user.getPhonenumber());
        userInfo.put("sex", user.getSex());
        userInfo.put("avatar", user.getAvatar());
        userInfo.put("deptId", user.getDeptId());
        userInfo.put("status", user.getStatus());
        userInfo.put("createTime", user.getCreateTime());
        return userInfo;
    }

    /**
     * 登录请求对象
     */
    public static class LoginRequest
    {
        @ApiParam(value = "用户名", required = true)
        private String username;
        
        @ApiParam(value = "密码", required = true)
        private String password;
        
        @ApiParam(value = "验证码")
        private String captcha;
        
        @ApiParam(value = "验证码UUID")
        private String uuid;

        public String getUsername()
        {
            return username;
        }

        public void setUsername(String username)
        {
            this.username = username;
        }

        public String getPassword()
        {
            return password;
        }

        public void setPassword(String password)
        {
            this.password = password;
        }

        public String getCaptcha()
        {
            return captcha;
        }

        public void setCaptcha(String captcha)
        {
            this.captcha = captcha;
        }

        public String getUuid()
        {
            return uuid;
        }

        public void setUuid(String uuid)
        {
            this.uuid = uuid;
        }
    }

    /**
     * 刷新Token请求对象
     */
    public static class RefreshTokenRequest
    {
        @ApiParam(value = "刷新Token", required = true)
        private String refreshToken;

        public String getRefreshToken()
        {
            return refreshToken;
        }

        public void setRefreshToken(String refreshToken)
        {
            this.refreshToken = refreshToken;
        }
    }
    

}